#!/usr/bin/python

import os, sys
import getopt
import jinja2


def usage():
    msg = '''
    protogen help message
    -------------------------------
    -c   Protocal class [ server | client ]
    -t   Output format [lua | as3 ] 
    -o   Output directory
    -p   Protocol file path
    '''
    print msg

def parse_opt(opts):
    config = {}
    for k, v in opts:
        config[k] = v
    
    required_check = [
        ('-c', 'Protocal class required'),
        ('-t', 'Output format required'),
        ('-o', 'Output directory required'),
        ('-p', 'Protocol file required'),
    ]

    for opt, errmsg in required_check:
        if opt not in config: 
            print errmsg
            return None 

    if config['-t'] not in ('lua', 'as3'):
        print "Error output format"
        return None 

    if config['-c'] not in ('server', 'client'):
        print "Error protocal class"
        return None 

    return config 




map1 = {'byte':'BYTE', 'short':'SHORT', 'int':'INT', 'string':'STRING'}
map2 = {'byte':'int', 'short':'int', 'int':'int', 'string':'String'}

def _asnode(node):
    result = []
    for n,t,l in node:
        if type(t) == tuple:
            result.append(_asnode(t))
            continue

        if t == 'string':
            result.append(map1[t])
            continue

        else:
            if l == 1:
                result.append(map1[t])
            if l > 1:
                result.append([map1[t]])

    return repr(result).replace("'", '')

def _aspara(node):
    result = []
    for n,t,l in node:
        if type(t) == tuple:
            result.append(_aspara(t))
            continue
        if t == 'string':
            result.append('%s:%s'%(n, map2[t]))
            continue
        else:
            if l == 1:
                result.append('%s:%s'%(n, map2[t]))
            if l > 1:
                result.append('%s:Array'%(n))

    return repr(result).replace("'", '').replace('[', '').replace(']', '')


def msgid(msgname):
    return "%s_%s"%(msgname[:2].upper(), msgname[2:].upper())

if __name__ == '__main__':
    if len(sys.argv) == 1:
        usage()
        sys.exit()

    try:
        opts,args=getopt.getopt(sys.argv[1:],'c:t:o:p:')
    except getopt.GetoptError:
        usage()
        sys.exit()

    config = parse_opt(opts)
    if not config: sys.exit()

    protofile = config['-p']
    if not os.path.exists(protofile):
        print "proto file '%s' not exists"%(protofile)
        sys.exit()

    curdir = os.path.dirname(os.path.abspath(__file__))

    sys.path.append(os.path.dirname(protofile))
    modfile = os.path.basename(protofile)
    protomod = modfile[:modfile.rfind('.')]   
    context = __import__(protomod) 

    tmp = [ p for p in dir(context) if not (p.startswith('__') and p.endswith('__'))] 
    Protos = [p for p in tmp if p.startswith('_')] + [p for p in tmp if not p.startswith('_')] 

    modname = {}
    asnode = {}
    aspara = {}
    for k in Protos:
        value = getattr(context,k)
        asnode[k] = _asnode(value)
        aspara[k] = _aspara(value)
        modname[value] = k
    
    isnode= lambda x: type(x) == tuple 
    patvar={'asnode':asnode, 'aspara':aspara, 'isnode':isnode,'modname':modname, 
            'keys':Protos, 'context':context, 'class':config['-c'], 
            'classname':protomod, 'msgid':msgid}

    patdict = {
        'lua':[('template.lua', '%s.lua'%(protomod))],
        'as3':[
            ('cg_message.as', 'CG%s.as'%(protomod)),
            ('gc_message.as', 'GC%s.as'%(protomod)),
            ('handler.as', '%sHandler.as'%(protomod))
         ],
    }

    for template, output in patdict[config['-t']]:
        template = os.path.join(curdir, "templates", template)
        result = jinja2.Template(open(template).read()).render(patvar)
        result_lines = []
        for line in result.split('\n'):
            if line.strip() == '': continue
            result_lines.append(line);

        #print '\n'.join(result_lines)
        fp = open(os.path.join(config['-o'], output), 'w')
        content = '\n'.join(result_lines) +'\n'
        if config['-t'] == 'lua':
            content = content.replace('end\nfunction', 'end\n\nfunction')
        fp.write(content)
    
